package pl.ydp.components.mathcell.mathcell.preprocessing.multicharacter
{
	import flash.geom.Point;
	import flash.geom.Rectangle;
	
	import pl.ydp.components.mathcell.mathrecognizer.Debug;
	import pl.ydp.components.mathcell.mathrecognizer.structures.Range;
	
	/** 
	 * Handles the functionality of cell with multiple characters.
	 * 
	 * Currently depreciated.
	 * 
	 * @see MultiCharacterContainer5
	 */
	public class MultiCharacterContainer
	{
		public function MultiCharacterContainer(pmaxCount:Number, pcellWidth:Number, pcellHeight:Number, playoutIsHorizontal:Boolean, precursiveLevels:Number)
		{
			_charactersPoints = new Array();
			_penPoints = new Array(); 
			maxCount = pmaxCount;
			cellWidth = pcellWidth;
			cellHeight = pcellHeight;
			charactersBounds = new Array;
			_characterOffsetsX = new Array;
			layoutIsHorizontal = playoutIsHorizontal;
			recursiveLevels = precursiveLevels;
		}
		
		// FIELDS & PROPERTIES
		
		private const CHARACTER_WIDTH_MIN:Number = 8;
		private const SPACING_MIN:Number = 2;
		
		public var cellWidth:Number;
		public var cellHeight:Number;
		public var layoutIsHorizontal:Boolean;
		public var recursiveLevels:Number;
		
		private var childContainer:MultiCharacterContainer;
		
		//------------------------- PROPERTIES ---------------------------------
		
		private var _charactersPoints:Array;
		
		public function get charactersPoints():Array{
			return _charactersPoints;
		} 
		
		private var charactersBounds:Array;
		
		private var _characterOffsetsX:Array;
		
		public function get characterOffsetsX():Array{
			return _characterOffsetsX;
		} 
		
		private var _penPoints:Array;
		
		public function set penPoints(pChPts:Array):void{
			_penPoints = pChPts;
			separate();
		} 
		
		public function get charactersCount():Number{
			return _charactersPoints.length;
		} 
		
		private var maxCount:Number;
		
		public function get charactersMaxCount():Number{
			return maxCount;
		} 
		
		private var childContainers:Array;
		
		
		//------------------------- METHODS ---------------------------------
				
		//-------------------------------------------------------------------
		
		private function separate():void{
			
			if (_penPoints.length == 0)
				return;
				
			if (_penPoints[0].length == 0)
				return;
			
			var x:Array ;
			for each (x in _penPoints)	
				Debug.saveLog(x, "before MCC::separate()");
			
			var r:Number;
			var ch:Number
			var stroke:Number;
			
			var penPointsRanges:Array = new Array();
			var charactersPenPointsIndexes:Array = new Array();
			var charactersPenPointsIndexesUsed:Array = new Array();
			var charactersPenPointsIndexesUsedCount:Number = 0;
			
			for (stroke = 0 ; stroke < _penPoints.length ; stroke++){
				var currRect:Rectangle = findBounds(_penPoints[stroke]);
				if (layoutIsHorizontal)
					penPointsRanges.push(new Range(currRect.left, currRect.right));
				else
					penPointsRanges.push(new Range(currRect.top, currRect.bottom));
			}
			
			charactersPenPointsIndexes.push(new Array);
			charactersPenPointsIndexes[0].push(0);
			charactersPenPointsIndexesUsed[0] = true;
			charactersPenPointsIndexesUsedCount = 1;
			
			for (r = 0 ; r < penPointsRanges.length ; r ++){
				charactersPenPointsIndexesUsed.push(false);
			}
			
			
			for (ch = 0 ; ch < penPointsRanges.length ; ch++){
				
				if (ch > 0)
					charactersPenPointsIndexes.push(new Array);
				
				for (r = 0 ; r < penPointsRanges.length ; r ++){
					if (charactersPenPointsIndexesUsed[r])
						continue;
						
					var add:Boolean = true;
					
					for each (var ppIndex:Number in charactersPenPointsIndexes[ch]){
						if ((penPointsRanges[ppIndex].min > penPointsRanges[r].max + SPACING_MIN  &&  
						penPointsRanges[ppIndex].min > penPointsRanges[r].min + SPACING_MIN + CHARACTER_WIDTH_MIN)
						||
						(penPointsRanges[ppIndex].max < penPointsRanges[r].min - SPACING_MIN  &&  
						penPointsRanges[ppIndex].max < penPointsRanges[r].max - SPACING_MIN - CHARACTER_WIDTH_MIN)
						){
							add = false;
							break;
						}
					}
							
						if (add) {
							charactersPenPointsIndexes[ch].push(r);
							charactersPenPointsIndexesUsed[r] = true;
							charactersPenPointsIndexesUsedCount++;
						}
						
				}
				
				if (charactersPenPointsIndexesUsedCount == penPointsRanges.length)
					break;
			}
			
			_charactersPoints = new Array;
			charactersBounds = new Array;
			
			for (ch = 0 ; ch < charactersPenPointsIndexes.length ; ch ++ ){
				_charactersPoints.push(new Array);
				
				for (stroke = 0 ; stroke < charactersPenPointsIndexes[ch].length ; stroke ++ ){
					_charactersPoints[ch].push(_penPoints[charactersPenPointsIndexes[ch][stroke]]);
				}
				
				var currBounds:Range = new Range(999999999, -999999999);
				
				for (stroke = 0 ; stroke < charactersPenPointsIndexes[ch].length ; stroke ++ ){
					if (currBounds.min > penPointsRanges[charactersPenPointsIndexes[ch][stroke]].min)
						currBounds.min = penPointsRanges[charactersPenPointsIndexes[ch][stroke]].min;
					if (currBounds.max < penPointsRanges[charactersPenPointsIndexes[ch][stroke]].max)
						currBounds.max = penPointsRanges[charactersPenPointsIndexes[ch][stroke]].max;
					
				}
				
				charactersBounds.push(currBounds);
				
			}
			
			for each (x in _charactersPoints[0])	
				Debug.saveLog(x, "after MCC::separate()");
				
			sortCharacters();
			
			centerCharactersX();
			
			for each (x in _charactersPoints[0])	
				Debug.saveLog(x, "after MCC::centerCharactersX()");
			
		}
		
		//-------------------------------------------------------------------
		
		
		private function sortCharacters():void{
			var output:Array = new Array;
			var ch:Number;
			var ch2:Number;
			var min:Number;
			var firstCoord:Number;
			var currCharacterIndex:Number;
			var used:Array = new Array;
			
			for (ch = 0 ; ch < _charactersPoints.length ; ch ++){
				used.push(false);
			}
			
			for (ch = 0 ; ch < _charactersPoints.length ; ch ++){
				min = 999999999;
				currCharacterIndex = -1;
				
				for (ch2 = 0 ; ch2 < _charactersPoints.length ; ch2 ++){
					
					if (layoutIsHorizontal)
						firstCoord = _charactersPoints[ch2][0][0].x;
					else
						firstCoord = _charactersPoints[ch2][0][0].y;
						
					if (firstCoord < min  &&  !used[ch2]){
						currCharacterIndex = ch2;
						min = firstCoord;
					}
				}
				
				if (currCharacterIndex != -1){
					output.push(_charactersPoints[currCharacterIndex]);
					used[currCharacterIndex] = true;
				}
				
			}
			
			_charactersPoints = output;
			
		}
		//-------------------------------------------------------------------
		
		
		private function centerCharactersX():void{
			
			var ch:Number;
			var stroke:Number;
			
			var centerX:Number;
			var currOffset:Number;
			var currCharWidth:Number;
			
			_characterOffsetsX = new Array;
			
			for (ch = 0 ; ch < _charactersPoints.length ; ch++){
		
				currCharWidth = charactersBounds[ch].max - charactersBounds[ch].min;
				centerX = charactersBounds[ch].min + currCharWidth/2;
				currOffset = charactersBounds[ch].min - (cellWidth - currCharWidth)/2;
				
				//for each (var charArr:Array in _charactersPoints)
					for each (var strokeArr:Array in _charactersPoints[ch])
						for each (var p:Point in  strokeArr)
							p.x -=  currOffset;
						
				_characterOffsetsX.push(currOffset);
				
				
			}
			
		}
		
				
		//-------------------------------------------------------------------
				
		private function findBounds(stroke:Array):Rectangle{
			if (stroke.length == 0)
				return new Rectangle(0,0,0,0);
			
			var min:Point = new Point(999999999,999999999);
			var max:Point = new Point(-999999999,-999999999);
			
			for each (var p:Point in stroke){
				if (p.x > max.x)
					max.x = p.x;
				if (p.y > max.y)
					max.y = p.y;
				if (p.x < min.x)
					min.x = p.x;
				if (p.x < min.x)
					min.y = p.y;
			}
				
			var rect:Rectangle = new Rectangle(min.x, min.y, max.x - min.x, max.y - min.y) ;
			
			return rect;
		}

	}
}